<script>
  import GroupSaveUpdate from '@/components/annex/group/save-update';

  import { dateFormat } from "assets/js/dateUtils";

  export default {
    layout: 'admin',
    components: {
      GroupSaveUpdate
    },
    data() {
      return {
        // 附件动态配置对象
        annex: {
          annexPreVo: {
            // 主键
            id: undefined,
            // 分类
            classify: undefined
          },
          // 分组列表
          groupList: [],
          // 附件配置列表
          configList: [
            // {
            //   id: data,
            //   groupId: this.activeGroupId,
            //   configJson: {
            //     fieldList: [
            //       {
            //         // 名称
            //         name: undefined,
            //         // 编码
            //         code: undefined,
            //         // 附件类型[0-图片 1-文件 2-视频]
            //         type: undefined,
            //         // 文件后缀
            //         suffix: undefined,
            //         // 是否必填[0-是 1-否]
            //         mustStatus: undefined,
            //         // 排序等级
            //         sort: undefined,
            //       }
            //     ],
            //     conditionList: [
            //       {
            //         // 值
            //         value: undefined,
            //         // 比较方式
            //         compareMode: undefined,
            //         // 比较方式名称
            //         compareModeName: undefined,
            //         // 数值
            //         equalsNumber: undefined,
            //         // 字符串值
            //         equalsString: undefined,
            //         // 数值列表
            //         numberList: [],
            //         // 匹配字符串值
            //         containString: undefined,
            //         // 数值范围-最小值
            //         minNumber: undefined,
            //         // 数值范围-最大值
            //         maxNumber: undefined,
            //         // 时间范围-最小值
            //         minDateTime: undefined,
            //         // 时间范围-最大值
            //         maxDateTime: undefined,
            //         // 日期范围-最小值
            //         minDate: undefined,
            //         // 日期范围-最大值
            //         maxDate: undefined,
            //         // 显示的值
            //         showValue: undefined
            //       }
            //     ]
            //   },
            //   sort: undefined
            // }
          ]
        },
        // 附件动态配置规则校验对象
        annexRules: {
          classify: [
            { required: true, message: '请选择分类', trigger: 'change' }
          ]
        },
        // 分类枚举列表
        classifyEnumList: [],
        // 条件枚举列表
        conditionEnumList: [],
        // 类型枚举列表
        typeEnumList: [],
        // 附件类型枚举列表[0-图片 1-文件 2-视频]
        fieldTypeEnumList: [
          {
            name: '图片',
            value: 0
          },
          {
            name: '文件',
            value: 1
          },
          {
            name: '视频',
            value: 2
          }
        ],
        // 点击的分组主键
        activeGroupId: undefined,
        // 得到鼠标焦点的分组主键
        hoverId: undefined,
        // 定时器
        timer: undefined,

        // 正在剪辑的附件字段主键
        editAnnexFieldId: undefined,
        // 正在编辑的字段行
        editFieldIndex: undefined,
        // 正在编辑的条件行
        editConditionIndex: undefined,
        // 正在编辑的附件字段
        editField: {
          // 名称
          name: undefined,
          // 编码
          code: undefined,
          // 附件类型[0-图片 1-文件 2-视频]
          type: undefined,
          // 附件类型名称
          typeName: undefined,
          // 文件后缀
          suffix: undefined,
          // 是否必填[0-是 1-否]
          mustStatus: undefined,
          // 排序等级
          sort: undefined,
        },
        // 正在编辑的附件条件
        editCondition: {
          // 值
          value: undefined,
          // 值名称
          valueName: undefined,
          // 比较方式
          compareMode: undefined,
          // 比较方式名称
          compareModeName: undefined,
          // 数值
          equalsNumber: undefined,
          // 字符串值
          equalsString: undefined,
          // 数值列表
          numberList: [],
          // 匹配字符串值
          containString: undefined,
          // 数值范围-最小值
          minNumber: undefined,
          // 数值范围-最大值
          maxNumber: undefined,
          // 时间范围-最小值
          minDateTime: undefined,
          // 时间范围-最大值
          maxDateTime: undefined,
          // 日期范围-最小值
          minDate: undefined,
          // 日期范围-最大值
          maxDate: undefined,
          // 显示的值
          showValue: undefined
        },
        // 省份列表
        provinceList: [],
        // 城市列表
        cityList: [],
        // 区县列表
        districtList: [],
        // 街道列表
        streetList: [],
        // 经营大类列表
        mainClassList: [],
        // 经营小类列表
        subClassList: [],
        // 是否必填枚举列表
        mustEnumList: [
          {
            name: '是',
            value: 0
          },
          {
            name: '否',
            value: 1
          }
        ],
        // 保存附件配置弹出框显示状态[true-显示 false-隐藏]
        saveAnnexDialogVisible: false,
        // 未填写完成数据行展示弹出框显示状态[true-显示 false-隐藏]
        unfinishedRowDialogVisible: false,

        // 未填写完成的数据行
        unfinishedRowList: [],

        // 按钮是否可被点击[false-可以被点击 true-不可被点击]
        buttonLoad: false,
        // 商店管理页面检索参数
        prePageSearchForm: '',
      }
    },
    computed: {
      // 主题颜色
      themeColor() {
        return this.$store.state.settings.theme;
      },
      // 点击的分组名称
      activeGroupName() {
        const activeGroupId = this.activeGroupId;
        const group = this.get(activeGroupId);
        if (!group) {
          return '';
        }
        return group.name;
      },
      // 显示的附件列表
      annexConfigList() {
        const configList = this.annex.configList;
        const activeGroupId = this.activeGroupId;
        if (!activeGroupId) {
          return [];
        }
        return configList.filter(field => field.groupId === activeGroupId);
      },
      // 显示的附件列表大小
      annexConfigListLength() {
        return this.annexConfigList.length;
      },
      // 值枚举列表
      valueEnumList() {
        const conditionEnumList = this.conditionEnumList;
        return conditionEnumList.map(conditionEnum => {
          return {
            name: conditionEnum.name,
            value: conditionEnum.value.value
          }
        })
      },
      // 比较方式枚举列表
      compareModeEnumList() {
        const conditionEnumList = this.conditionEnumList;
        const editCondition = this.editCondition;
        if (!editCondition.value) {
          return [];
        }
        const conditionEnum = conditionEnumList.find(conditionEnum => conditionEnum.value.value === editCondition.value);
        if (!conditionEnum) {
          return [];
        }
        return conditionEnum.value.compareModeList;
      },
      // 数值列表
      numberEnumList() {
        const editCondition = this.editCondition;
        if (!editCondition.value) {
          return [];
        }
        // 返回对应的枚举列表
        if (editCondition.value === 1) {
          return this.provinceList;
        } else if (editCondition.value === 2) {
          return this.cityList;
        } else if (editCondition.value === 3) {
          return this.districtList;
        } else if (editCondition.value === 4) {
          return this.streetList;
        } else if (editCondition.value === 51) {
          return this.mainClassList;
        } else if (editCondition.value === 52) {
          return this.subClassList;
        }
        return [];
      }
    },
    filters: {
      // 值映射成名称
      valueFormat(value, list) {
        for (let item of list) {
          if (item.value === value) {
            return item.name;
          }
        }
        return '';
      }
    },
    created() {
      if (process.client) {
        const params = this.$route.params;
        const id = params.id;

        // 记录上一个页面的参数
        this.prePageSearchForm = params.prePageSearchForm;
        this.annex.annexPreVo.id = id;
        this.getEnum();
        if (!!id) {
          // 获取配置详情
          this.getAnnex();
        }
      }

    },
    methods: {
      /**
       * 获取页面枚举方法
       */
      getEnum() {
        this.$axios.$get('/annex/add/enum')
          .then(({ data }) => {
            if (!this.annex.annexPreVo.id) {
              this.annex.annexPreVo.id = data.id;
            }
            this.classifyEnumList = data.classifyEnumList;
            this.conditionEnumList = data.conditionEnumList;
          })
          .catch(() => {});
      },
      /**
       * 获取附件动态配置数据方法
       */
      getAnnex() {
        this.buttonLoad = true;
        this.$axios.$get('/annex/get', { params: { id: this.annex.annexPreVo.id }})
          .then(({ data }) => {
            const annexPreDto = data.annexPreDto;

            const annex = this.annex;
            const annexPreVo = annex.annexPreVo;
            for (let propKey in annexPreVo) {
              if (annexPreDto.hasOwnProperty(propKey)) {
                annexPreVo[propKey] = annexPreDto[propKey];
              }
            }
            annex.groupList = data.annexGroupList;
            annex.configList = data.annexConfigList;

            if (annex.configList.length > 0) {
              this.activeGroupId = annex.configList[0].groupId;
            }
          })
          .catch(() => {})
          .finally(() => {
            this.buttonLoad = false;
          });
      },
      /**
       * 附件动态配置分组节点拖拽事件
       * @param node     拖拽节点
       * @param endNode  结束节点
       * @param dropType 放置位置
       * @param event    事件
       */
      nodeDropHandle(node, endNode, dropType, event) {
        const data = node.data;
        const endData = endNode.data;

        if (dropType === 'inner') {
          /*
            节点移入
           */
          // 节点存储
          data.sort = 1;
          data.parentId = endData.id;
        } else {
          /*
            节点位置变动
            1、前后位置变动
            2、节点移出
           */
          let children = this.annex.groupList;
          if (endData.parentId !== 0) {
            let parent = this.get(endData.parentId);
            if (parent) {
              data.parentId = parent.id;

              children = parent.children || [];
            }
          }
          // 更新列表排序等级
          children.forEach((group, i) => group.sort = i + 1);
        }
      },
      /**
       * 获取节点对象
       * @param id 主键
       */
      get(id) {
        const queue = [...this.annex.groupList];
        while (queue.length > 0) {
          let group = queue.shift();
          if (group.id === id) {
            return group;
          }
          if (group.children && group.children.length > 0) {
            queue.push(...group.children);
          }
        }
        return undefined;
      },
      /**
       * 鼠标移入事件
       * @param {Object} group 分组对象
       */
      mouseenterHandle(group) {
        this.timer = setTimeout(() => {
          this.hoverId = group.id;
          clearTimeout(this.timer);
        }, 500);
      },
      /**
       * 鼠标移出事件
       */
      mouseleaveHandle() {
        this.hoverId = undefined;
        clearTimeout(this.timer);
      },
      /**
       * 选择分组事件
       */
      changeGroupHandle(annexGroup) {
        if (this.activeGroupId === annexGroup.id) {
          // 点击相同分组
          return;
        }
        /*
          进行填写完成条件判断
         */
        const annexConfigList = this.annexConfigList;
        const unfinishedRowList = this.unfinishedRowList;
        // 计算未填写完成数据行
        this.mathUnfinishedRow(annexConfigList);
        // 切换点击分组
        this.activeGroupId = annexGroup.id;

        if (unfinishedRowList.length > 0) {
          this.unfinishedRowDialogVisible = true;
        }
      },
      /**
       * 打开分组新增/修改弹出框事件
       * @param {Object} annexGroup 分组对象
       */
      openGroupSaveUpdateDialogHandle(annexGroup) {
        this.$refs.groupSaveUpdate.openDialog(annexGroup, this.annex.groupList);
      },
      /**
       * 保存分组事件
       * @param {Object} annexGroup 分组对象
       */
      saveGroupHandle(annexGroup) {
        if (annexGroup.parentId === '0') {
          this.annex.groupList.push(annexGroup);
          return;
        }
        const parentGroup = this.get(annexGroup.parentId);
        if (!parentGroup) {
          this.$message.warning("父级分组不存在，添加失败");
          return;
        }
        let children = parentGroup.children;
        if (!children) {
          children = [];
          this.$set(parentGroup, 'children', children);
        }
        children.push(annexGroup);
      },
      /**
       * 修改分组事件
       * @param {Object} annexGroup 分组对象
       */
      updateGroupHandle(annexGroup) {
        const _group = this.get(annexGroup.id);
        if (!_group) {
          this.$message.warning("分组不存在，修改失败");
          return;
        }
        for (let propKey in _group) {
          if (annexGroup.hasOwnProperty(propKey)) {
            _group[propKey] = annexGroup[propKey];
          }
        }
      },
      /**
       * 删除分组事件
       * @param {Object} annexGroup 分组对象
       */
      deleteGroupHandle(annexGroup) {
        this.$confirm(`确定删除’${annexGroup.name}‘分组及其附件配置吗？`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(() => {
            const annex = this.annex;
            // 删除分组
            annex.groupList = annex.groupList.filter(group => group.id !== annexGroup.id);
            // 删除附件配置
            annex.configList = annex.configList.filter(config => config.groupId !== annexGroup.id);

            if (this.activeGroupId === annexGroup.id) {
              this.activeGroupId = undefined;
            }
          })
          .catch(() => {});
      },
      /**
       * 添加附件字段
       */
      addConfigHandle() {
        this.buttonLoad = true;
        this.$axios.$get('/primary/get/one')
          .then(({ data }) => {
            const annexConfigList = this.annexConfigList;
            // 获取等级最大的元素
            const maxAnnexConfig = annexConfigList.reduce((maxAnnexConfig, annexConfig) => {
              return maxAnnexConfig.sort > annexConfig.sort ? maxAnnexConfig : annexConfig;
            }, { sort: 0 });
            let sort = maxAnnexConfig.sort + 1;

            const configList = this.annex.configList;
            configList.push({
              id: data,
              groupId: this.activeGroupId,
              configJson: {
                fieldList: [
                  {
                    name: '',
                    code: '',
                    type: undefined,
                    typeName: undefined,
                    suffix: '',
                    mustStatus: undefined,
                    sort: undefined,
                  }
                ],
                conditionList: [
                  {
                    value: undefined,
                    valueName: undefined,
                    compareMode: undefined,
                    compareModeName: undefined,
                    equalsNumber: undefined,
                    equalsString: '',
                    numberList: [],
                    containString: '',
                    minNumber: undefined,
                    maxNumber: undefined,
                    minDateTime: undefined,
                    maxDateTime: undefined,
                    minDate: undefined,
                    maxDate: undefined,
                    showValue: undefined
                  }
                ]
              },
              sort: sort
            });
          })
          .catch(() => {})
          .finally(() => {
            this.buttonLoad = false;
          })
      },
      /**
       * 删除附件字段事件
       * @param {number} index 附件字段所在数组下标
       */
      deleteAnnexFieldHandle(index) {
        this.$confirm(`确定删除第‘${index}’个附件吗?`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
        .then(() => {
          this.annex.configList.splice(index - 1, 1);
        })
        .catch(() => {});
      },
      /**
       * 确认附件修改事件
       * @param {boolean} bool         修改对象[true-附件字段 false-附件条件]
       * @param {string}  annexFieldId 附件字段主键
       */
      confirmEditHandle(bool, annexFieldId) {
        const annexConfig = this.getAnnexConfig(annexFieldId);
        if (!annexConfig) {
          return;
        }
        this.editAnnexFieldId = undefined;
        if (bool) {
          /*
            确认附件修改
           */
          const field = annexConfig.configJson.fieldList[this.editFieldIndex];
          const editField = this.editField;
          for (let propKey in editField) {
            field[propKey] = editField[propKey];
          }
          this.editFieldIndex = undefined;
        } else {
          /*
            确认条件修改
           */
          const condition = annexConfig.configJson.conditionList[this.editConditionIndex];
          const editCondition = this.editCondition;
          for (let propKey in editCondition) {
            condition[propKey] = editCondition[propKey];
          }
          this.editConditionIndex = undefined;
        }
      },
      /**
       * 取消附件修改事件
       * @param {boolean} bool 修改对象[true-附件字段 false-附件条件]
       */
      cancelEditHandle(bool) {
        this.editAnnexFieldId = undefined;
        if (bool) {
          /*
            取消附件修改
           */
          this.editFieldIndex = undefined;
        } else {
          /*
            取消条件修改
           */
          this.editConditionIndex = undefined;
        }
      },
      /**
       * 修改附件事件
       * @param {boolean} bool         修改对象[true-附件字段 false-附件条件]
       * @param {string}  annexFieldId 附件字段主键
       * @param {number}  index        对象所在数组下表
       */
      editHandle(bool, annexFieldId, index) {
        this.editAnnexFieldId = annexFieldId;
        const annexConfig = this.getAnnexConfig(annexFieldId);
        if (!annexConfig) {
          return;
        }
        if (bool) {
          /*
            附件修改
           */
          const field = annexConfig.configJson.fieldList[index];
          const editField = this.editField;
          for (let propKey in editField) {
            editField[propKey] = field[propKey];
          }
          this.editFieldIndex = index;
        } else {
          /*
            条件修改
           */
          const condition = annexConfig.configJson.conditionList[index];
          const editCondition = this.editCondition;
          for (let propKey in editCondition) {
            editCondition[propKey] = condition[propKey];
          }
          this.editConditionIndex = index;
        }
      },
      /**
       * 添加附件事件
       * @param {boolean} bool         修改对象[true-附件字段 false-附件条件]
       * @param {string}  annexFieldId 附件字段主键
       * @param {number}  index        对象所在数组下表
       */
      addHandle(bool, annexFieldId, index) {
        const annexConfig = this.getAnnexConfig(annexFieldId);
        if (!annexConfig) {
          return;
        }
        if (bool) {
          /*
            添加附件
           */
          const newField = {
            name: undefined,
            code: undefined,
            type: undefined,
            suffix: undefined,
            mustStatus: undefined,
            sort: undefined,
          }
          annexConfig.configJson.fieldList.splice(index + 1, 0, newField);
        } else {
          /*
            添加条件
           */
          const newCondition = {
            value: undefined,
            compareMode: undefined,
            equalsNumber: undefined,
            equalsString: undefined,
            numberList: [],
            containString: undefined,
            minNumber: undefined,
            maxNumber: undefined,
            minDateTime: undefined,
            maxDateTime: undefined,
            minDate: undefined,
            maxDate: undefined
          }
          annexConfig.configJson.conditionList.splice(index + 1, 0, newCondition);
        }
      },
      /**
       * 复制附件事件
       * @param {boolean} bool         修改对象[true-附件字段 false-附件条件]
       * @param {string}  annexFieldId 附件字段主键
       * @param {number}  index        对象所在数组下表
       */
      copyHandle(bool, annexFieldId, index) {
        const annexConfig = this.getAnnexConfig(annexFieldId);
        if (!annexConfig) {
          return;
        }
        if (bool) {
          /*
            复制附件
           */
          const field = annexConfig.configJson.fieldList[index];
          const newField = JSON.parse(JSON.stringify(field));
          annexConfig.configJson.fieldList.splice(index + 1, 0, newField);
        } else {
          const condition = annexConfig.configJson.conditionList[index];
          const newCondition = JSON.parse(JSON.stringify(condition));
          annexConfig.configJson.conditionList.splice(index + 1, 0, newCondition);
        }
      },
      /**
       * 删除附件事件
       * @param {boolean} bool         修改对象[true-附件字段 false-附件条件]
       * @param {string}  annexFieldId 附件字段主键
       * @param {number}  index        对象所在数组下表
       */
      deleteHandle(bool, annexFieldId, index) {
        const annexConfig = this.getAnnexConfig(annexFieldId);
        if (!annexConfig) {
          return;
        }
        let promise;
        if (bool) {
          /*
            删除附件
           */
          if (annexConfig.configJson.fieldList.length <= 1) {
            this.notify('warning', '删除失败', '无法全部删除附件');
            return;
          }
          promise = this.$confirm(`确定删除第‘${index + 1}’个附件吗？`, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          });
        } else {
          /*
            删除条件
           */
          if (annexConfig.configJson.conditionList.length <= 1) {
            this.notify('warning', '删除失败', '无法全部删除条件');
            return;
          }
          promise = this.$confirm(`确定删除第‘${index + 1}’个条件吗？`, '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          });
        }
        promise.then(() => {
          if (bool) {
            /*
              删除附件
             */
            annexConfig.configJson.fieldList.splice(index, 1);
          } else {
            /*
              删除条件
             */
            annexConfig.configJson.conditionList.splice(index, 1);
          }
        }).catch(() => {});
      },
      /**
       * 获取附件字段对象
       * @param id 附件字段主键
       */
      getAnnexConfig(id) {
        const annexField = this.annexConfigList.find(annexField => annexField.id === id);
        if (!annexField) {
          this.$message.warning("找不到附件对象");
          return undefined;
        }
        return annexField;
      },
      /**
       * 选择附件字段类型事件
       */
      changeFieldTypeHandle() {
        const editField = this.editField;
        const fieldTypeEnum = this.fieldTypeEnumList.find(fieldTypeEnum => fieldTypeEnum.value ===  editField.type);
        if (!!fieldTypeEnum) {
          editField.typeName = fieldTypeEnum.name;
        }
      },
      /**
       * 选择条件值事件
       */
      changeConditionValueHandle() {
        const editCondition = this.editCondition;
        const valueEnum = this.valueEnumList.find(valueEnum => valueEnum.value === editCondition.value);
        if (!!valueEnum) {
          editCondition.valueName = valueEnum.name;
        }
        editCondition.compareMode = undefined;
        editCondition.compareModeName = undefined;
        editCondition.equalsNumber = undefined;
        editCondition.equalsString = undefined;
        editCondition.numberList = [];
        editCondition.containString = undefined;
        editCondition.minNumber = undefined;
        editCondition.maxNumber = undefined;
        editCondition.minDateTime = undefined;
        editCondition.maxDateTime = undefined;
        editCondition.minDate = undefined;
        editCondition.maxDate = undefined;
        editCondition.showValue = undefined;

        if (editCondition.value === 1) {
          // 省份
          this.getProvinceList();
        } else if (editCondition.value === 2) {
          // 城市
          this.getCityList();
        } else if (editCondition.value === 3) {
          // 区县
          this.getDistrictList()
        } else if (editCondition.value === 4) {
          // 街道
          this.getStreetList();
        } else if (editCondition.value === 51) {
          // 商店经营大类

        } else if (editCondition.value === 52) {
          // 商店经营小类

        }
      },
      /**
       * 选择条件比较模式事件
       */
      changeCompareModeHandle() {
        const compareModeEnumList = this.compareModeEnumList;
        const editCondition = this.editCondition;

        const compareModeEnum = compareModeEnumList.find(compareModeEnum =>
          compareModeEnum.value === editCondition.compareMode);
        if (compareModeEnum) {
          editCondition.compareModeName = compareModeEnum.name;
        }

        editCondition.equalsNumber = undefined;
        editCondition.equalsString = undefined;
        editCondition.numberList = [];
        editCondition.containString = undefined;
        editCondition.minNumber = undefined;
        editCondition.maxNumber = undefined;
        editCondition.minDateTime = undefined;
        editCondition.maxDateTime = undefined;
        editCondition.minDate = undefined;
        editCondition.maxDate = undefined;
        editCondition.showValue = undefined;
      },
      /**
       * 数值范围输入事件
       */
      inputRangeNumberHandle() {
        const editCondition = this.editCondition;
        editCondition.showValue = editCondition.minNumber + '-' + editCondition.maxNumber;
      },
      /**
       * 选择时间事件
       */
      changeRangeDatetimeHandle() {
        const editCondition = this.editCondition;

        let showValue = '';
        if (!!editCondition.minDateTime) {
          showValue += dateFormat(new Date(editCondition.minDateTime));
        }
        if (!!editCondition.maxDateTime) {
          showValue += ' - '
          showValue += dateFormat(new Date(editCondition.maxDateTime));
        }
        editCondition.showValue = showValue;
      },
      /**
       * 选择日期事件
       */
      changeRangeDateHandle() {
        const editCondition = this.editCondition;

        let showValue = '';
        if (!!editCondition.minDate) {
          showValue += dateFormat(new Date(editCondition.minDate));
        }
        if (!!editCondition.maxDate) {
          showValue += ' - '
          showValue += dateFormat(new Date(editCondition.maxDate));
        }
        editCondition.showValue = showValue;
      },
      /**
       * 页面滚动事件
       * @param {string} refName 标签ref名称
       */
      scrollHandle(refName) {
        const targetDiv = this.$refs[refName][0].$el;
        let contentBoxDiv = this.$refs.contentBox.$el;
        // 获取元素距离顶部距离
        let top = targetDiv.offsetTop - contentBoxDiv.offsetTop - 90;
        // 滚动到指定div
        this.$refs.contentBox.$el.scrollTo({
          top: top,
          behavior: "smooth",
        });
      },
      /**
       * 选择列表值事件
       * TODO 如果存在字符串枚举列表，则可以将改成匹配两种列表的逻辑
       */
      changeNumberListHandle() {
        clearTimeout(this.timer);
        this.timer = setTimeout(() => {
          const editCondition = this.editCondition;
          const numberEnumList = this.numberEnumList;

          let value = '';
          for (let number of editCondition.numberList) {
            const numberEnum = numberEnumList.find(numberEnum => numberEnum.value === number);
            if (!!numberEnum) {
              value += numberEnum.name;
              value += ',';
            }
          }
          if (value.length > 1) {
            value = value.substring(0, value.length - 1);
          }
          editCondition.showValue = value;

          clearTimeout(this.timer);
        }, 700);
      },
      /**
       * 打开保存附件配置弹出框事件
       */
      openSaveAnnexDialogHandle() {
        this.saveAnnexDialogVisible = true;

        const configList = this.annex.configList;
        // 计算未填写完成数据行
        this.mathUnfinishedRow(configList);
      },
      /**
       * 计算得到未填写完成数据行方法
       * @param configList 附件配置列表
       */
      mathUnfinishedRow(configList) {
        const unfinishedRowList = this.unfinishedRowList;

        configList.forEach((config, index) => {
          let groupId = config.groupId;
          let group = this.get(groupId);

          let configJson = config.configJson;
          let fieldList = configJson.fieldList;
          let conditionList = configJson.conditionList;
          /*
            判断字段是否填写完成
           */
          let propKeys = ['name', 'code', 'type', 'mustStatus', 'sort'];
          fieldList.forEach((field, fieldIndex) => {
            for (let propKey of propKeys) {
              if (!field[propKey] && field[propKey] !== 0) {
                unfinishedRowList.push({
                  groupId: groupId,
                  groupName: group.name,
                  index: index + 1,
                  fieldIndex: fieldIndex + 1,
                  conditionIndex: undefined
                });
                break;
              }
            }
          });
          /*
            判断条件是否填写完成
           */
          propKeys = ['value', 'compareMode', 'showValue'];
          conditionList.forEach((condition, conditionIndex) => {
            for (let propKey of propKeys) {
              if (!condition[propKey] && condition[propKey] !== 0) {
                unfinishedRowList.push({
                  groupId: groupId,
                  groupName: group.name,
                  index: index + 1,
                  fieldIndex: undefined,
                  conditionIndex: conditionIndex + 1
                });
                break;
              }
            }
          });
        });
      },
      /**
       * 关闭保存附件配置弹出框事件
       */
      closeSaveAnnexDialogHandle() {
        this.$nextTick(() => {
          this.saveAnnexDialogVisible = false;
          this.unfinishedRowDialogVisible = false;
        });
        this.unfinishedRowList = [];
      },
      /**
       * 点击未填写完成数据行事件
       * 进行页面跳转
       * @param {Object} unfinishedRow 未填写完成数据行对象
       */
      clickUnfinishedRowHandle(unfinishedRow) {

        this.activeGroupId = unfinishedRow.groupId;

        // 关闭弹出框
        this.closeSaveAnnexDialogHandle();

        this.$nextTick(() => {
          // 页面滚动到置顶位置
          this.scrollHandle('annexConfig' + unfinishedRow.index);
        });
      },
      /**
       * 附件动态配置提交事件
       */
      submitHandle() {
        this.$refs.annexForm.validate()
          .then(() => {
            this.buttonLoad = true;

            const annex = this.annex;

            // 拆分分组列表
            let groupList = [], queue = [...annex.groupList];
            while (queue.length > 0) {
              let group = queue.pop();
              groupList.push(group);

              if (group.children && group.children.length > 0) {
                queue.push(...group.children);
              }
            }

            let body = {
              annexPreVo: annex.annexPreVo,
              groupList: groupList,
              configList: annex.configList
            }
            const url = !!this.$route.params.id ? '/annex/update' : '/annex/save';
            return this.$axios.$put(url, body)
          })
          .then(() => {
            this.notify('success', '操作提示', `${!!this.$route.params.id ? '修改' : '保存'}附件配置成功`);

            this.backPrePageHandle();
          })
          .catch(() => {})
          .finally(() => {
            this.buttonLoad = false;
          });
      },
      /**
       * 返回商店管理页事件
       */
      backPrePageHandle() {
        // 跳回管理页面
        this.$router.replace({ name: 'admin-annex', params: { searchForm: this.prePageSearchForm }});
      },
      /**
       * 获取省份列表
       */
      getProvinceList() {
        if (this.provinceList.length !== 0) {
          return;
        }
        this.$axios.$get("/region-code/provinceList")
          .then(({ data }) => {
            let provinceList = [];
            for (let item of data) {
              provinceList.push(...item.list);
            }
            this.provinceList = provinceList;
          })
          .catch(() => {});
      },
      /**
       * 获取城市列表
       */
      getCityList() {
        if (this.cityList.length !== 0) {
          return;
        }
        this.$axios.$get("/region-code/cityList")
          .then(({ data }) => {
            let cityList = [];
            for (let item of data) {
              cityList.push(...item.list);
            }
            this.cityList = cityList;
          })
          .catch(() => {});
      },
      /**
       * 获取城市列表
       */
      getDistrictList() {
        if (this.districtList.length !== 0) {
          return;
        }
        this.$axios.$get("/region-code/districtList")
          .then(({ data }) => {
            let districtList = [];
            for (let item of data) {
              districtList.push(...item.list);
            }
            this.districtList = districtList;
          })
          .catch(() => {});
      },
      /**
       * 获取城市列表
       */
      getStreetList() {
        if (this.streetList.length !== 0) {
          return;
        }
        this.$axios.$get("/region-code/streetList")
          .then(({ data }) => {
            let streetList = [];
            for (let item of data) {
              streetList.push(...item.list);
            }
            this.streetList = streetList;
          })
          .catch(() => {});
      },

    }
  }
</script>

<template>
  <div class="config-page">
    <el-row :gutter="15">
      <el-col :span="5">
        <el-card :body-style="{ padding: '10px' }" shadow="hover" class="left-box">
          <div class="btn-box">
            <el-button type="text" size="medium" @click="openGroupSaveUpdateDialogHandle(undefined)"
                       class="add-btn">
              添加分组
            </el-button>
          </div>
          <el-tree
            :data="annex.groupList"
            node-key="id"
            :expand-on-click-node="false"
            default-expand-all
            draggable
            @node-drop="nodeDropHandle"
          >
            <div slot-scope="{ node, data }" @mouseenter="mouseenterHandle(data)" @mouseleave="mouseleaveHandle"
                 style="width: 100%">
              <span @click="changeGroupHandle(data)" class="el-tree-node__label">{{ data.name }}</span>
              <span v-if="data.children && data.children.length > 0" class="el-tree-node__label children-count">
                      ({{ data.children.length }})
                    </span>
              <span v-show="hoverId === data.id" :style="{ '--theme': themeColor }"
                    @click="openGroupSaveUpdateDialogHandle(data)"
                    class="el-tree-node__label btn update-btn">
                修改
              </span>
              <span v-show="hoverId === data.id" :style="{ '--theme': themeColor }"
                    @click="deleteGroupHandle(data)"
                    class="el-tree-node__label btn delete-btn">
                删除
              </span>
            </div>
          </el-tree>
        </el-card>
      </el-col>
      <el-col :span="19" ref="contentBox" class="config-box">
        <el-card :body-style="{ padding: '10px' }" shadow="never" class="opt-box">
          <div class="save-btn">
            <el-button :disabled="annex.groupList.length === 0" type="primary" size="mini" plain
                       @click="openSaveAnnexDialogHandle">
              保存
            </el-button>
            <el-button type="info" size="mini" plain @click="backPrePageHandle">
              返回
            </el-button>
          </div>
          <div class="tag-box">
            <el-tag
              v-if="!!activeGroupName"
              size="medium"
              disable-transitions
              effect="plain"
              class="config-num"
            >
              {{ activeGroupName }}
            </el-tag>
            <el-tag
              v-for="num in annexConfigListLength"
              :key="'tag' + num"
              size="medium"
              closable
              disable-transitions
              @click="scrollHandle('annexConfig' + num)"
              @close="deleteAnnexFieldHandle(num)"
              class="config-num"
            >
              {{ num }}
            </el-tag>
            <el-tag v-if="activeGroupId" size="medium" effect="plain" @click="addConfigHandle" class="add-btn">
              新增
            </el-tag>
          </div>
        </el-card>
        <el-card v-for="(annexConfig, index) in annexConfigList" :key="'annexConfig' + index"
                 :ref="'annexConfig' + (index + 1)"
                 :body-style="{ padding: '10px' }"
                 shadow="never" class="field-box">
          <div class="field-tag">
            <el-tag class="tag">{{ index + 1 }}</el-tag>
          </div>
          <div class="field-title">
            附件
          </div>
          <el-table
            :data="annexConfig.configJson.fieldList"
            class="field-table"
          >
            <el-table-column prop="name" label="名称">
              <template v-slot="{ row, $index }">
                <template v-if="editAnnexFieldId === annexConfig.id && editFieldIndex === $index">
                    <el-input v-model="editField.name" size="small" clearable placeholder="请输入附件名称"
                              class="width17percent">
                    </el-input>
                </template>
                <span v-else>{{ row.name }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="code" label="编码">
              <template v-slot="{ row, $index }">
                <template v-if="editAnnexFieldId === annexConfig.id && editFieldIndex === $index">
                  <el-input v-model="editField.code" size="small" clearable placeholder="请输入附件编码"
                            class="width17percent">
                  </el-input>
                </template>
                <span v-else>{{ row.code }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="type" label="类型">
              <template v-slot="{ row, $index }">
                <template v-if="editAnnexFieldId === annexConfig.id && editFieldIndex === $index">
                  <el-select v-model="editField.type" size="small" placeholder="请选择附件类型"
                             @change="changeFieldTypeHandle">
                    <el-option
                      v-for="fieldTypeEnum in fieldTypeEnumList"
                      :key="'fieldTypeEnum' + fieldTypeEnum.value"
                      :label="fieldTypeEnum.name"
                      :value="fieldTypeEnum.value">
                    </el-option>
                  </el-select>
                </template>
                <span v-else>{{ row.type | valueFormat(fieldTypeEnumList) }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="suffix" label="后缀">
              <template v-slot="{ row, $index }">
                <template v-if="editAnnexFieldId === annexConfig.id && editFieldIndex === $index">
                  <el-input v-model="editField.suffix" size="small" clearable placeholder="请输入附件编码"
                            class="width17percent">
                  </el-input>
                </template>
                <span v-else>{{ row.suffix }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="mustStatus" label="是否必填">
              <template v-slot="{ row, $index }">
                <template v-if="editAnnexFieldId === annexConfig.id && editFieldIndex === $index">
                  <el-select v-model="editField.mustStatus" size="small" placeholder="请选择是否必填"
                             @change="changeFieldTypeHandle">
                    <el-option
                      v-for="mustEnum in mustEnumList"
                      :key="'mustEnum' + mustEnum.value"
                      :label="mustEnum.name"
                      :value="mustEnum.value">
                    </el-option>
                  </el-select>
                </template>
                <span v-else>{{ row.mustStatus | valueFormat(mustEnumList) }}</span>
              </template>
            </el-table-column>
            <el-table-column align="center" prop="sort" label="序号" width="90">
              <template v-slot="{ row, $index }">
                <template v-if="editAnnexFieldId === annexConfig.id && editFieldIndex === $index">
                  <el-input v-model="editField.sort" size="small" placeholder="序号" maxlength="5"
                            class="width17percent">
                  </el-input>
                </template>
                <span v-else>{{ row.sort }}</span>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="170">
              <template v-slot="{ row, $index }">
                <div v-if="editAnnexFieldId === annexConfig.id && editFieldIndex === $index">
                  <el-button type="text" @click="confirmEditHandle(true, annexConfig.id)">确定</el-button>
                  <el-button type="text" @click="cancelEditHandle(true)">取消</el-button>
                </div>
                <div v-else-if="editAnnexFieldId === undefined">
                  <el-button type="text" @click="editHandle(true, annexConfig.id, $index)">编辑</el-button>
                  <el-button type="text" @click="addHandle(true, annexConfig.id, $index)">新增</el-button>
                  <el-button type="text" @click="copyHandle(true, annexConfig.id, $index)">复制</el-button>
                  <el-button type="text" @click="deleteHandle(true, annexConfig.id, $index)">
                    删除
                  </el-button>
                </div>
                <div v-else>&nbsp;</div>
              </template>
            </el-table-column>
          </el-table>
          <div class="field-title">
            条件
          </div>
          <el-table
            :data="annexConfig.configJson.conditionList"
            class="condition-table"
          >
            <el-table-column prop="value" label="字段">
              <template v-slot="{ row, $index }">
                <template v-if="editAnnexFieldId === annexConfig.id && editConditionIndex === $index">
                  <el-select v-model="editCondition.value" size="small" placeholder="请选择字段"
                             @change="changeConditionValueHandle" class="width90percent">
                    <el-option
                      v-for="valueEnum in valueEnumList"
                      :key="'valueEnum' + valueEnum.value"
                      :label="valueEnum.name"
                      :value="valueEnum.value">
                    </el-option>
                  </el-select>
                </template>
                <span v-else>{{ row.value | valueFormat(valueEnumList) }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="compareMode" label="计算模式">
              <template v-slot="{ row, $index }">
                <template v-if="editAnnexFieldId === annexConfig.id && editConditionIndex === $index">
                  <el-select v-model="editCondition.compareMode" size="small" placeholder="请选择计算模式"
                             @change="changeCompareModeHandle" class="width90percent">
                    <el-option
                      v-for="compareModeEnum in compareModeEnumList"
                      :key="'compareModeEnum' + compareModeEnum.value"
                      :label="compareModeEnum.name"
                      :value="compareModeEnum.value">
                    </el-option>
                  </el-select>
                </template>
                <span v-else>{{ row.compareModeName }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="type" label="值">
              <template v-slot="{ row, $index }">
                <template v-if="editAnnexFieldId === annexConfig.id && editConditionIndex === $index">
                  <el-input v-if="editCondition.compareMode === 0 || editCondition.compareMode === 1"
                            v-model="editCondition.equalsNumber" size="small"
                            placeholder="请输入内容" @input="editCondition.showValue = $event"
                            class="width90percent">
                  </el-input>
                  <el-input v-if="editCondition.compareMode === 2 || editCondition.compareMode === 3"
                            v-model="editCondition.equalsString" size="small"
                            placeholder="请输入内容"
                            @input="editCondition.showValue = $event"
                            class="width90percent">
                  </el-input>
                  <el-select v-if="editCondition.compareMode === 4 || editCondition.compareMode === 5"
                             v-model="editCondition.numberList" size="small" multiple clearable filterable
                             placeholder="请选择类型" @change="changeNumberListHandle" class="width90percent">
                    <el-option v-for="numberEnum in numberEnumList" :key="'numberEnum' + numberEnum.value"
                               :label="numberEnum.name"
                               :value="numberEnum.value">
                    </el-option>
                  </el-select>
                  <el-input v-if="editCondition.compareMode === 6 || editCondition.compareMode === 7"
                            v-model="editCondition.containString" size="small"
                            placeholder="请输入内容"
                            @input="editCondition.showValue = $event"
                            class="width90percent">
                  </el-input>
                  <el-input v-if="editCondition.compareMode === 8"
                            v-model="editCondition.minNumber" size="small" placeholder="请输入内容"
                            @input="inputRangeNumberHandle"
                            class="width45percent">
                  </el-input>
                  <span v-if="editCondition.compareMode === 8" class="range">至</span>
                  <el-input v-if="editCondition.compareMode === 8"
                            v-model="editCondition.maxNumber" size="small" placeholder="请输入内容"
                            @input="inputRangeNumberHandle"
                            class="width45percent">
                  </el-input>
                  <el-date-picker
                    v-if="editCondition.compareMode === 9"
                    v-model="editCondition.minDateTime"
                    size="small"
                    type="datetime"
                    placeholder="选择开始时间"
                    value-format="timestamp"
                    @change="changeRangeDatetimeHandle"
                    class="width95percent">
                  </el-date-picker>
                  <span v-if="editCondition.compareMode === 9" class="range">至</span>
                  <el-date-picker
                    v-if="editCondition.compareMode === 9"
                    v-model="editCondition.maxDateTime"
                    size="small"
                    type="datetime"
                    placeholder="选择结束时间"
                    value-format="timestamp"
                    @change="changeRangeDatetimeHandle"
                    class="width95percent">
                  </el-date-picker>
                  <el-date-picker
                    v-if="editCondition.compareMode === 10"
                    v-model="editCondition.minDate"
                    size="small"
                    type="date"
                    placeholder="选择开始日期"
                    value-format="timestamp"
                    @change="changeRangeDateHandle"
                    class="width95percent">
                  </el-date-picker>
                  <span v-if="editCondition.compareMode === 10" class="range">至</span>
                  <el-date-picker
                    v-if="editCondition.compareMode === 10"
                    v-model="editCondition.maxDate"
                    size="small"
                    type="date"
                    placeholder="选择结束日期"
                    value-format="timestamp"
                    @change="changeRangeDateHandle"
                    class="width95percent">
                  </el-date-picker>
                </template>
                <span v-else>{{ row.showValue }}</span>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="170">
              <template v-slot="{ row, $index }">
                <div v-if="editAnnexFieldId === annexConfig.id && editConditionIndex === $index">
                  <el-button type="text" @click="confirmEditHandle(false, annexConfig.id)">确定</el-button>
                  <el-button type="text" @click="cancelEditHandle(false)">取消</el-button>
                </div>
                <div v-else-if="editAnnexFieldId === undefined">
                  <el-button type="text" @click="editHandle(false, annexConfig.id, $index)">编辑</el-button>
                  <el-button type="text" @click="addHandle(false, annexConfig.id, $index)">新增</el-button>
                  <el-button type="text" @click="copyHandle(false, annexConfig.id, $index)">复制</el-button>
                  <el-button type="text" @click="deleteHandle(false, annexConfig.id, $index)">
                    删除
                  </el-button>
                </div>
                <div v-else>&nbsp;</div>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-col>
    </el-row>

    <!-- 添加/修改分组弹出框 -->
    <GroupSaveUpdate @save="saveGroupHandle" @update="updateGroupHandle" ref="groupSaveUpdate" />

    <el-dialog
      title="保存附件配置"
      :visible.sync="saveAnnexDialogVisible"
      width="45%"
      top="10vh"
      :before-close="closeSaveAnnexDialogHandle"
      :close-on-click-modal="false"
      class="save-annex-dialog"
    >
      <template v-if="unfinishedRowList.length > 0">
        <div class="tip">
          <i class="el-icon-warning icon"></i>
          以下数据行未填写完成，点击跳转到对应位置继续填写完成后再进行保存
        </div>
        <div class="unfinished-row-box">
          <div v-for="(unfinishedRow, index) in unfinishedRowList" :key="'unfinishedRow' + index"
               @click="clickUnfinishedRowHandle(unfinishedRow)" :style="{ '--theme': themeColor }"
               class="unfinished-row">
            <span>第</span>
            <span>{{ unfinishedRow.index }}</span>
            <span>个配置，</span>
            <span class="name">{{ !!unfinishedRow.fieldIndex ? '字段' : '条件' }}</span>
            <span>第</span>
            <span>{{ !!unfinishedRow.fieldIndex ? unfinishedRow.fieldIndex : unfinishedRow.conditionIndex }}</span>
            <span>行数据</span>
          </div>
        </div>
      </template>
      <template v-else>
        <el-form size="small" :model="annex.annexPreVo" :rules="annexRules" status-icon label-width="100px"
                 @submit.native.prevent="submitHandle" ref="annexForm">
          <el-form-item label="分类" prop="classify">
            <el-select v-model="annex.annexPreVo.classify" size="small" clearable placeholder="请选择附件类型"
                       class="width90percent">
              <el-option
                v-for="classifyEnum in classifyEnumList"
                :key="'classifyEnum' + classifyEnum.value"
                :label="classifyEnum.name"
                :value="classifyEnum.value">
              </el-option>
            </el-select>
          </el-form-item>
        </el-form>
      </template>

      <div slot="footer">
        <el-button :disabled="unfinishedRowList.length > 0 || buttonLoad" type="primary" @click="submitHandle">
          确 定
        </el-button>
      </div>
    </el-dialog>

    <el-dialog
      title="切换分组提示"
      :visible.sync="unfinishedRowDialogVisible"
      width="45%"
      top="10vh"
      :before-close="closeSaveAnnexDialogHandle"
      :close-on-click-modal="false"
      class="unfinished-row-dialog"
    >
      <div class="tip">
        <i class="el-icon-warning icon"></i>
        以下数据行未填写完成，您可以点击跳转到对应位置继续填写
      </div>
      <div class="unfinished-row-box">
        <div v-for="(unfinishedRow, index) in unfinishedRowList" :key="'unfinishedRow' + index"
             @click="clickUnfinishedRowHandle(unfinishedRow)" :style="{ '--theme': themeColor }"
             class="unfinished-row">
          <span>第</span>
          <span>{{ unfinishedRow.index }}</span>
          <span>个配置，</span>
          <span class="name">{{ !!unfinishedRow.fieldIndex ? '字段' : '条件' }}</span>
          <span>第</span>
          <span>{{ !!unfinishedRow.fieldIndex ? unfinishedRow.fieldIndex : unfinishedRow.conditionIndex }}</span>
          <span>行数据</span>
        </div>
      </div>
      <div slot="footer">
        <el-button type="primary" @click="closeSaveAnnexDialogHandle">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<style scoped>
  .config-page .left-box {
    height: calc(100vh - 132px);
    overflow-y: auto;
  }
  .config-page .left-box .btn-box {
    height: 35px;
    line-height: 35px;
    border-bottom: 1px solid #DCDFE6;
    margin-bottom: 10px;
  }
  .config-page .left-box .btn-box .add-btn {
    margin-left: 10px;
    cursor: pointer;
  }
  .config-page .config-box {
    height: calc(100vh - 132px);
    overflow-y: auto;
    position: relative;
  }
  .config-page .config-box .opt-box {
    margin-bottom: 10px;
    position: sticky;
    top: 0;
    z-index: 10;
  }
  .config-page .config-box .opt-box .save-btn {
    margin-bottom: 7px;
  }
  .config-page .config-box .opt-box .tag-box {
    line-height: 35px;
  }
  .config-page .config-box .opt-box .tag-box .config-num {
    font-size: 14px;
    margin-right: 18px;
    cursor: pointer;
  }
  .config-page .config-box .opt-box .tag-box .add-btn {
    font-size: 14px;
    cursor: pointer;
  }
  .config-page .config-box .field-box {
    margin-top: 10px;
  }
  .config-page .config-box .field-box .field-tag {
    width: 100%;
    margin-bottom: 10px;
  }
  .config-page .config-box .field-box .field-tag .tag {
    width: 50px;
    text-align: center;
    font-size: 15px;
  }
  .config-page .config-box .field-box .field-title {
    padding-left: 5px;
    margin-bottom: 10px;
    font-size: 15px;
    height: 35px;
    line-height: 35px;
    background-color: #F2F6FC;
    border-radius: 3px;
  }
  .config-page .config-box .field-box .field-table,
  .config-page .config-box .field-box .condition-table {
    margin-bottom: 10px;
  }

  .config-page .config-box .field-box .annex-box,
  .config-page .config-box .field-box .condition-box {
    padding: 5px 0;
    border-bottom: 1px solid #E4E7ED;
  }
  .config-page .config-box .field-box .annex-box .annex-title,
  .config-page .config-box .field-box .condition-box .condition-title {
    text-align: right;
    width: 50px;
    display: inline-block;
  }
  .config-page .config-box .field-box .condition-table .range {
    font-size: 14px;
  }
  .config-page >>> .el-tree .el-tree-node {
    white-space: normal;
  }
  .config-page >>> .el-tree .el-tree-node .el-tree-node__content {
    height: 100%;
    line-height: 22px;
    align-items: start;
  }
  .config-page >>> .children-count {
    color: #67C23A;
  }
  .config-page .btn {
    margin-left: 10px;
  }
  .config-page .btn.update-btn {
    --theme: #3a8ee6;
    color: var(--theme);
  }
  .config-page .btn.delete-btn {
    color: #ff4949;
  }
</style>

<style>
  .unfinished-row-dialog .tip {
    font-size: 16px;
    margin-bottom: 7px;
    line-height: 30px;
  }
  .unfinished-row-dialog .tip .icon {
    color: #e6a23c;
    font-size: 17px;
  }
  .unfinished-row-dialog .unfinished-row-box .unfinished-row {
    --theme: #409EFF;
    margin-left: 23px;
    line-height: 30px;
    font-size: 15px;
    cursor: pointer;
  }
  .unfinished-row-dialog .unfinished-row-box .unfinished-row:hover {
    color: var(--theme);
  }
  .unfinished-row-dialog .unfinished-row-box .unfinished-row .name {
    font-weight: bold;
  }
</style>

<style>
  .save-annex-dialog .tip {
    font-size: 16px;
    margin-bottom: 7px;
    line-height: 30px;
  }
  .save-annex-dialog .tip .icon {
    color: #e6a23c;
    font-size: 17px;
  }
  .save-annex-dialog .unfinished-row-box {
    max-height: 400px;
    overflow-y: auto;
  }
  .save-annex-dialog .unfinished-row-box .unfinished-row {
    --theme: #409EFF;
    margin-left: 23px;
    line-height: 30px;
    font-size: 15px;
    cursor: pointer;
  }
  .save-annex-dialog .unfinished-row-box .unfinished-row:hover {
    color: var(--theme);
  }
  .save-annex-dialog .unfinished-row-box .unfinished-row .name {
    font-weight: bold;
  }
</style>

<style scoped>
  .config-page .width45percent {
    width: 45%;
  }
  .config-page .width90percent {
    width: 90%;
  }
  .config-page .width95percent {
    width: 95%;
  }
</style>
